#!/usr/bin/ppython

import math, threading
import direct.showbase.ShowBase, direct.task, panda3d.core
import geocube

colorActive  = (0,1,0)
colorPassive = (1,0,0)

class VirtualLEDCube(direct.showbase.ShowBase.ShowBase):
	def __init__(self, width, depth, height, size=1):
		direct.showbase.ShowBase.ShowBase.__init__(self)
		
		self.width = width
		self.depth = depth
		self.height = height
		self.size = size
		
		self.jobLock = threading.Lock()
		self.jobs = []
		
		self.layers = []
		
		for i in range(height):
			layer = VirtualLEDLayer(width, depth, size)
			
			layer.setPos(0, 0, i)
			layer.reparentTo(self.render)
			self.layers.append(layer)
		
		self.taskMgr.add(self.onStep, "onStep")
	
	def addJob(self, job):
		self.jobLock.acquire()
		self.jobs.append(job)
		self.jobLock.release()
	
	def onStep(self, task):
		if self.jobLock.acquire(False):
			for job in self.jobs:
				job(self)
			self.jobs = []
			self.jobLock.release()
		
		freq = 0.5
		
		angleHDegrees = math.sin(task.time * freq) * 20 + 180
		angleHRadians = angleHDegrees * (math.pi / 180.0)
		
		x = (self.width - 1) / 2 + 20.0 * math.sin(angleHRadians)
		y = (self.depth - 1) / 2 - 20.0 * math.cos(angleHRadians)
		z = (self.height / 2) - 0.5 + math.cos(task.time * freq) * (self.height - 1) * 0.75
		
		h = angleHDegrees
		p = -20 * math.cos(task.time * freq)
		r = 0
		
		self.camera.setHpr(h,p,r)
		self.camera.setPos(x,y,z)
		
		return direct.task.Task.cont
	
	def setEnabled(self, x,y,z, enabled):
		self.layers[z].rows[y].columns[x].setEnabled(enabled)
	

class VirtualLEDLayer(panda3d.core.NodePath):
	def __init__(self, width, depth, size):
		panda3d.core.NodePath.__init__(self, "Layer")
		
		self.rows = []
		
		
		for i in range(depth):
			shading = float(i) / (depth - 1) * 0.25 + 0.75
			
			row = VirtualLEDRow(width, size, shading)
			
			row.setPos(0, i, 0)
			row.reparentTo(self)
			self.rows.append(row)

class VirtualLEDRow(panda3d.core.NodePath):
	def __init__(self, width, size, shading):
		panda3d.core.NodePath.__init__(self, "Row")
		
		self.columns = []
		
		for i in range(width):
			column = VirtualLEDColumn(size, shading)
			
			column.setPos(width-1-i, 0, 0)
			column.reparentTo(self)
			self.columns.append(column)

class VirtualLEDColumn(panda3d.core.NodePath):
	def __init__(self, size, shading):
		panda3d.core.NodePath.__init__(self, "Column")
		
		self.enabled = False
		self.setScale(size, size, size)
		
		self.cubeActive  = geocube.create("cube", [i * shading for i in colorActive ] + [1] )
		self.cubePassive = geocube.create("cube", [i * shading for i in colorPassive] + [1] )
		
		self.cubePathActive  = self.attachNewNode(self.cubeActive)
		self.cubePathPassive = self.attachNewNode(self.cubePassive)
		
		self.cubePathActive.detachNode()
	
	def setEnabled(self, enabled):
		if enabled:
			if self.enabled:
				return
			
			self.enabled = True
			self.cubePathPassive.detachNode()
			self.cubePathActive.reparentTo(self)
		else:
			if not self.enabled:
				return
			
			self.enabled = False
			self.cubePathActive.detachNode()
			self.cubePathPassive.reparentTo(self)
	

if __name__ == "__main__":
	cube = VirtualLEDCube(5, 5, 10, 0.1)
	cube.run()

